/* readclass/readclass/main.go, 
   Written by, Sohail Qayum Malik[sqm@hackers.pk] 
    
/* For it to be an executable, this should be a main package, this file should reside in a directory(folder) such as the name of the folder ends up being the name of the resulting executable */
/* This file should be named main.go */ 
/* Issue following command to compile and install this file to bin directory... 
       go install readclass/readclass  
   Where the path to source is... 
       src/readclass/readclass/main.go */
       
/* Incomplete, more functionality and more clear comments can be added later */       
       
package main

import (

   "os" 
   "log"
   "fmt"
   "flag" /* src/pkg/flag/flag.go */
   
   "readclass/functions"
)

type Command struct {
  
   /* 
      The camel casing is intentional... 
      making the first letter of the field name gets it exported 
    */
   /*
     The one line usage message
     cmd-name , the message...
    */
   UsageLine	string
   
   Flag	 	flag.FlagSet
}

func (c *Command) run(args []string) {
}

/* The other way is the following one... */
var help bool
var version bool

func usage() {

   flag.PrintDefaults()
   fmt.Fprintf(os.Stderr, "usage: C:\\> %s cmd\n", os.Args[0])
   os.Exit(2)
}

/* 
 * Treat each init() function as a constructor method(or Java init() method) 
 * these are automatically called even before main() gets called 
 */
func init() {

   /*
     All of the following methods and their other counter parts which return
     pointer variables internally call the methods of type FlagSet struct {}
     In the flag(the module) the instance is...
     var commandLine := NewFlagSet()...
     Each internal method(this *NewFlagSet) gets the this-> pointer which has the address of var commandLine and it thus work on commandLine        
    */

   /* Since both of them are non-declaration statements that is why they must be made part of some function body */ 
   flag.BoolVar(&help, "help", false, "For help screen")
   flag.BoolVar(&help, "h", false, "For help screen(short)")
   
   /* Like wise */
   flag.BoolVar(&version, "version", false, "For version screen")
   flag.BoolVar(&version, "v", false, "For version screen(short)")
} 

func main() {

   /* 
      A statement in pkg/flag/flag.go 
      it serves the same purpose as does the Command::Flag 
      The function NewFlagSet() returns an address of a instance of...
      type FlagSet struct {}
    */
   /* var commandLine := NewFlagSet() */
   
   /* 
      In flag module we the following statement ....
      var usage = func { }
      So we are merely assigning our usage method 
    */
   flag.Usage = usage
   /* 
     This method internally calls the parse method of struct FlagSet 
     The method of FlagSet gets a this-> pointer which has the address of
     above mentioned... var commandLine := NewFlagSet()
   */
   flag.Parse()
   
   /* Now args is all the non flag command line arguments */
   args := flag.Args()
  
   /* 
    *  The only permitted forms for the boolean flags...
    *  -help
    *  -help=[0 | 1 | false | true]
    *  The other form...
    *  help [0 | 1 | false | true] is not permitted for boolean flags 
    */ 
   if help == true {
   
      fmt.Println("-help = on")
      return
   }   
   
   if version == true {
   
      fmt.Println("-version = on")
      return
   }
 
   if len(args) == 0 {
      
      fmt.Println("Some of the options from the under given list must be used")         
      flag.Usage() 
      os.Exit(0)
   }
   
   /* Process non-flag command line arguments */
   /* idx is in the state of don't care */ 
   for _, name := range args {
   
      fd, err := os.Open(name) /* Read-only open */ 
     
      if err != nil {
     
         log.Fatal(err)
      }
   
      fi, err := fd.Stat() 
     
      if err != nil {
     
         log.Fatal(err)
      }
     
      if fi.Size() == 0 {
        
         fd.Close()
         continue
      }

      /* data []byte, count int64 */
      data, count := functions.Getdata(fd, fi.Size())
      
      fd.Close()
      
      /* Process the entities of a Java class file one by one */

      /* cfo, ClassFile Object */      
      /* cfo := */ functions.GetClassFile(data, count)

/*
      fmt.Println(cfo.Magic)
      fmt.Println(cfo.Minor_version)
*/      
       
   }
}

